package com.blueocean_health.care.management.service;

import com.blueocean_health.care.management.common.LocalManager;
import com.blueocean_health.care.management.domain.base.SysResult;
import com.blueocean_health.care.management.domain.dto.*;
import com.blueocean_health.care.management.domain.vo.LoginDataVo;
import com.blueocean_health.care.management.em.LocalManagerType;
import com.blueocean_health.care.management.mapper.HomeCalcMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class HomeCalcService {

    @Autowired
    private HomeCalcMapper homeCalcMapper;

    @Scheduled(cron = "0 5 0 * * ?")
    public void scheduled(){
        calc(null);
    }

    //获取下拉列表
    public SysResult param(HomeCalcRequest request) {
        List<HomeCalcType> typeList = homeCalcMapper.queryType();
        List<HomeCalcType> yearList = typeList.stream().filter(bean -> bean.getLabel().length() == 4).collect(Collectors.toList());
        List<HomeCalcType> monthList = typeList.stream().filter(bean -> bean.getLabel().length() > 4).collect(Collectors.toList());

        HomeCalcType year = new HomeCalcType();
        year.setLabel("年");
        year.setValue("1");
        year.setChildren(yearList);

        HomeCalcType month = new HomeCalcType();
        month.setLabel("月");
        month.setValue("2");
        month.setChildren(monthList);

        Map<String, Object> result = new HashMap<>();
        result.put("default", new HomeCalcDefaultInfo("2", new SimpleDateFormat("yyyy-MM").format(new Date())));
        result.put("list", Arrays.asList(year, month));

        return SysResult.ok(result);
    }

    //获取数据
    public SysResult data(HomeCalcRequest request) {
        if (request == null || request.getValue() == null || "".equals(request.getValue())) {
            request = new HomeCalcRequest();
        }
        String value = request.getValue();

        List<HomeCalcRespInfo> list = homeCalcMapper.queryData(request);

        HomeCalcRespInfo title = list.stream().filter(bean -> value.equals(bean.getTime())).findAny().orElse(null);
        List<HomeCalcRespInfo> body = list.stream().filter(bean -> bean.getTime().length() == 10).collect(Collectors.toList());

        Map<String, Object> result = new HashMap<>();
        result.put("title", title);
        result.put("body", body);

        return SysResult.ok(result);
    }

    //计算数据, 正常情况是每天凌晨计算一次
    public SysResult calc(HomeCalcRequest request) {
        long sTime = System.currentTimeMillis();
        //获取当前登录的用户的信息
        LoginDataVo loginDataVo = LocalManager.getVal(LocalManagerType.LOGIN_DATA);
        String teamId = null;

        if(loginDataVo != null) teamId = loginDataVo.getUser().getTeamId();
        if (teamId == null) teamId = "50";

        //根据当前teamID获取其下所有的医院ID
        List<Integer> hospitalIds = homeCalcMapper.queryHospitalListByTeamId(teamId);

        //获取当前时间
        Date nowStartTime = getNowStartTime();

        {
            try {
                if(request != null){
                    String time = request.getValue();
                    if (time != null) {
                        nowStartTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(time);
                    }

                    List<Integer> ids = request.getHospitalIds();
                    if(ids != null && ids.size() != 0){
                        hospitalIds.clear();
                        hospitalIds.addAll(ids);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        //查询当前医院的所有订单
        List<HomeCalcOrderInfo> orderInfoList = homeCalcMapper.queryList(nowStartTime);
        //查询退款订单
        List<HomeCalcRefundInfo> refundInfoList = homeCalcMapper.queryRefundList(nowStartTime);

        //过滤订单为当前所需医院ID的订单
        List<HomeCalcOrderInfo> list = orderInfoList.stream().filter(bean -> hospitalIds.contains(Integer.parseInt(bean.getHospitalId()))).collect(Collectors.toList());
        //过滤退款订单为当前所需医院ID的订单
        List<HomeCalcRefundInfo> filterRefundInfoList = refundInfoList.stream().filter(bean -> hospitalIds.contains(bean.getHospitalId())).collect(Collectors.toList());

        calcDay(list, filterRefundInfoList);

        long eTime = System.currentTimeMillis();

        return SysResult.ok(eTime - sTime);
    }



    private void calcDay(List<HomeCalcOrderInfo> list, List<HomeCalcRefundInfo> refundInfoList) {

        //患者个数计算, 天级别数据汇总, 月度级别数据汇总, 年度级别数据汇总
        Map<String, List<String>> pcMap = new HashMap<>();
        Map<String, List<String>> pcMonthMap = new HashMap<>();
        Map<String, List<String>> pcYearMap = new HashMap<>();
        calcPatient(list, pcMap, pcMonthMap, pcYearMap);

        //计算上工量
        Map<String, List<String>> ncMap = new HashMap<>();
        Map<String, List<String>> ncMonthMap = new HashMap<>();
        Map<String, List<String>> ncYearMap = new HashMap<>();
        calcNurse(list, ncMap, ncMonthMap, ncYearMap);

        //计算应收金额
        Map<String, Double> priceCountMap = new HashMap<>();
        Map<String, Double> priceCountMonthMap = new HashMap<>();
        Map<String, Double> priceCountYearMap = new HashMap<>();
        calcPrice(list, priceCountMap, priceCountMonthMap, priceCountYearMap);

        //计算订单收款金额
        Map<String, Double> paymentCountMap = new HashMap<>();
        Map<String, Double> paymentCountMonthMap = new HashMap<>();
        Map<String, Double> paymentCountYearMap = new HashMap<>();
        calcPayment(list, paymentCountMap, paymentCountMonthMap, paymentCountYearMap, refundInfoList);

        //计算提成金额, 多对多: 服务费用 * 提成比例, 其他: 工资
        Map<String, Double> payCountMap = new HashMap<>();
        Map<String, Double> payCountMonthMap = new HashMap<>();
        Map<String, Double> payCountYearMap = new HashMap<>();
        calcPay(list, payCountMap, payCountMonthMap, payCountYearMap);


        //计算天级别的数据
        List<HomeCalcRespInfo> dayList = calcResult(pcMap, ncMap, priceCountMap, paymentCountMap, payCountMap);
        //计算月级别的数据
        List<HomeCalcRespInfo> monthList = calcResult(pcMonthMap, ncMonthMap, priceCountMonthMap, paymentCountMonthMap, payCountMonthMap);
        //计算年级别的数据
        List<HomeCalcRespInfo> yearList = calcResult(pcYearMap, ncYearMap, priceCountYearMap, paymentCountYearMap, payCountYearMap);


        //先清空原有数据
        homeCalcMapper.deleteData();
        //计算完毕后把数据插入到数据库
        if( dayList.size() > 0 ) {
            homeCalcMapper.insertBatchDate(dayList);
        }
        if (monthList.size() > 0) {
            homeCalcMapper.insertBatchDate(monthList);
        }
        if (yearList.size() > 0) {
            homeCalcMapper.insertBatchDate(yearList);
        }
    }

    private List<HomeCalcRespInfo> calcResult(Map<String, List<String>> pcMap, Map<String, List<String>> ncMap, Map<String, Double> priceCountMap, Map<String, Double> paymentCountMap, Map<String, Double> payCountMap) {
        Set<String> timeSet = new HashSet<>();
        timeSet.addAll(pcMap.keySet());
        timeSet.addAll(ncMap.keySet());
        timeSet.addAll(priceCountMap.keySet());
        timeSet.addAll(paymentCountMap.keySet());
        timeSet.addAll(payCountMap.keySet());
        List<HomeCalcRespInfo> result = new ArrayList<>();
        timeSet.forEach(time -> {
            HomeCalcRespInfo resp = new HomeCalcRespInfo();
            resp.setTime(time);
            resp.setPatientCount(pcMap.get(time) == null ? 0: pcMap.get(time).size());
            resp.setNurseCount(ncMap.get(time) == null ? 0 : ncMap.get(time).size());
            resp.setReceiveAmount(priceCountMap.get(time));
            resp.setPaymentAmount(paymentCountMap.get(time));
            resp.setCommissionAmount(payCountMap.get(time));
            //计算毛利率, (应收金额 - 提成金额) / 应收金额
            resp.calc();
            result.add(resp);
        });
        return result;
    }

    private void calcPay(List<HomeCalcOrderInfo> list, Map<String, Double> payCountMap, Map<String, Double> payCountMonthMap, Map<String, Double> payCountYearMap) {
        list.forEach(bean -> {
            long sTime = bean.getBeginTime().getTime();
            long eTime = bean.getEndTime().getTime();

            int index = 0;
            do{
                String time = longToString(sTime);

                double count;

                int hours = (int) ((eTime - sTime)/L_HOUR);
                index ++;
                if(!"4".equals(bean.getServiceType())){
                    if(bean.getOneDayPay() == null || bean.getOneDayPay() == 0){
                        count = 0;
                    }else{
                        if(sTime + L_DAY < eTime) {
                            count = bean.getOneDayPay();
                        }else if(sTime + L_DAY == eTime || ("2".equals(bean.getOrderTypeFlag()) && hours == 12)){
                            count = bean.getOneDayPay() + new BigDecimal(bean.getTotalPay()).remainder(new BigDecimal(bean.getOneDayPay())).setScale(BigDecimal.ROUND_HALF_DOWN, 2).doubleValue();
                        }else{
                            if(bean.getEndTime().getTime() - bean.getBeginTime().getTime() <= L_DAY){
                                count = bean.getTotalPay();
                            }else{
                                count = bean.getTotalPay() - (index - 1) * bean.getOneDayPay();
                            }
                        }
                    }
                }else{
                    if(bean.getActualDayPrice() == null || bean.getActualDayPrice() == 0){
                        count = 0;
                    }else{
                        if(sTime + L_DAY < eTime) {
                            count = bean.getActualDayPrice();
                        }else if(sTime + L_DAY == eTime || ("2".equals(bean.getOrderTypeFlag()) && hours == 12)){
                            count = bean.getActualDayPrice() + new BigDecimal(bean.getActualTotalPrice()).remainder(new BigDecimal(bean.getActualDayPrice())).setScale(BigDecimal.ROUND_HALF_DOWN, 2).doubleValue();
                        }else{
                            if(bean.getEndTime().getTime() - bean.getBeginTime().getTime() <= L_DAY){
                                count = bean.getActualTotalPrice();
                            }else{
                                count = bean.getActualTotalPrice() - (index - 1) * bean.getActualDayPrice();
                            }
                        }
                    }
                    count = count * bean.getProportions() / 100;
                }

                //如果是退款
                if("3".equals(bean.getOrderType())){
                    count /= -1;
                }

                if(payCountMap.containsKey(time)){
                    count = payCountMap.get(time) + count;
                }
                payCountMap.put(time, count);

                sTime += L_DAY;
            }while(sTime < eTime);
        });

        payCountMap.forEach((dTime, count) -> {
            String mTime = dTime.substring(0, MONTH_TIME_PATTERN.length());
            if(!payCountMonthMap.containsKey(mTime)){
                payCountMonthMap.put(mTime, 0.0);
            }
            payCountMonthMap.put(mTime, payCountMonthMap.get(mTime) + count);

            String yTime = dTime.substring(0, YEAR_TIME_PATTERN.length());
            if(!payCountYearMap.containsKey(yTime)){
                payCountYearMap.put(yTime, 0.0);
            }
            payCountYearMap.put(yTime, payCountYearMap.get(yTime) + count);
        });
    }

    private void calcPayment(List<HomeCalcOrderInfo> list, Map<String, Double> paymentCountMap, Map<String, Double> paymentCountMonthMap, Map<String, Double> paymentCountYearMap, List<HomeCalcRefundInfo> refundInfoList) {
        Map<String, List<HomeCalcOrderInfo>> orderMap = list.stream().collect(Collectors.groupingBy(HomeCalcOrderInfo::getOrderId));
        refundInfoList.forEach(bean -> {
            double count = 0;
            String serviceId = bean.getServiceId();
            if(serviceId == null || "".equals(serviceId)){//缴费订单
                List<HomeCalcOrderInfo> servicesList = orderMap.get(bean.getOrderId());
                if(servicesList == null) return ;
                List<HomeCalcOrderInfo> realList = servicesList.stream().distinct().collect(Collectors.toList());
                count += realList.stream().map(HomeCalcOrderInfo::getActualTotalPrice).reduce((all, one) -> all += one).orElse(0.0);
            }else{//退款订单
                //根据退款ServiceID查找对应的金额
                Double price = homeCalcMapper.queryPrice(serviceId);
                if(price != null){
                    count -= price;
                }
            }
            String time = longToString(bean.getTime().getTime());
            if(paymentCountMap.containsKey(time)){
                count += paymentCountMap.get(time);
            }
            paymentCountMap.put(time, count);
        });

        paymentCountMap.forEach((dTime, count) -> {
            String mTime = dTime.substring(0, MONTH_TIME_PATTERN.length());
            if(!paymentCountMonthMap.containsKey(mTime)){
                paymentCountMonthMap.put(mTime, 0.0);
            }
            paymentCountMonthMap.put(mTime, paymentCountMonthMap.get(mTime) + count);

            String yTime = dTime.substring(0, YEAR_TIME_PATTERN.length());
            if(!paymentCountYearMap.containsKey(yTime)){
                paymentCountYearMap.put(yTime, 0.0);
            }
            paymentCountYearMap.put(yTime, paymentCountYearMap.get(yTime) + count);
        });
    }

    private void calcPrice(List<HomeCalcOrderInfo> list, Map<String, Double> priceCountMap, Map<String, Double> priceCountMonthMap, Map<String, Double> priceCountYearMap) {
        //应收金额 = 服务明细的实际日单价, 不足一天小时价格计算
        Map<String, Integer> servicesMap = new HashMap<>();
        list.forEach(bean -> {
            String serviceId = bean.getServiceId();
            if(servicesMap.containsKey(serviceId)){
                return ;
            }
            servicesMap.put(serviceId, null);

            long sTime = bean.getBeginTime().getTime();
            long eTime = bean.getEndTime().getTime();

            int index = 0 ;
            do{
                String time = longToString(sTime);

                double count;
                if(bean.getActualDayPrice() == null || bean.getActualDayPrice() == 0){
                    count = 0;
                }else{
                    int hours = (int) ((eTime - sTime)/L_HOUR);
                    if(sTime + L_DAY < eTime) {
                        count = bean.getActualDayPrice();
                        index ++;
                    }else if(sTime + L_DAY == eTime || ("2".equals(bean.getOrderTypeFlag()) && hours == 12)){
                        count = new BigDecimal(bean.getActualDayPrice()).add(new BigDecimal(bean.getActualTotalPrice()).remainder(new BigDecimal(bean.getActualDayPrice()))).setScale(BigDecimal.ROUND_HALF_DOWN, 2).doubleValue();
                        index ++;
                    }else{
                        if(bean.getEndTime().getTime() - bean.getBeginTime().getTime() <= L_DAY){
                            count = bean.getActualTotalPrice();
                        }else{
                            count = bean.getActualTotalPrice() - index * bean.getActualDayPrice();
                        }
                    }
                }

                //如果是退款
                if("3".equals(bean.getOrderType())){
                    count /= -1;
                }

                if(priceCountMap.containsKey(time)){
                    count = priceCountMap.get(time) + count;
                }
                priceCountMap.put(time, count);

                sTime += L_DAY;
            }while(sTime < eTime);
        });

        priceCountMap.forEach((dTime, count) -> {
            String mTime = dTime.substring(0, MONTH_TIME_PATTERN.length());
            if(!priceCountMonthMap.containsKey(mTime)){
                priceCountMonthMap.put(mTime, 0.0);
            }
            priceCountMonthMap.put(mTime, priceCountMonthMap.get(mTime) + count);
        });

        priceCountMonthMap.forEach((mTime, count) -> {
            String yTime = mTime.substring(0, YEAR_TIME_PATTERN.length());
            if(!priceCountYearMap.containsKey(yTime)){
                priceCountYearMap.put(yTime, 0.0);
            }
            priceCountYearMap.put(yTime, priceCountYearMap.get(yTime) + count);
        });
    }

    private void calcNurse(List<HomeCalcOrderInfo> list, Map<String, List<String>> ncMap, Map<String, List<String>> ncMonthMap, Map<String, List<String>> ncYearMap) {
        Map<String, HomeCalcOrderInfo> serviceBeanMap = new HashMap<>();
        list.forEach(bean -> {
            serviceBeanMap.put(bean.getServiceId(), bean);

            //计算是增加还是减少
            boolean isAdd = !"3".equals(bean.getOrderType());

            String key = bean.getServiceId() + bean.getWorkerId();
            long orderDiff = bean.getEndTime().getTime() - bean.getBeginTime().getTime();
            long sTime = bean.getBeginTime().getTime(),
                    eTime = bean.getEndTime().getTime(),
                    offset = getDayOffset(bean.getBeginTime()),
                    prevOffset = 0;

            if(!isAdd){
                prevOffset = getDayOffset(serviceBeanMap.get(bean.getRefundServiceId()).getBeginTime());
            }

            do{
                String time = longToString(sTime);

                if(!ncMap.containsKey(time)){
                    ncMap.put(time, new ArrayList<>());
                }
                if(isAdd){
                    ncMap.get(time).add(key);
                }else{
                    /*if(prevOffset >= offset){
                        ncMap.get(time).remove(key);
                    }*/
                    /*long diff = L_DAY;
                    if(eTime - sTime >= diff || eTime - sTime == orderDiff % diff || eTime - sTime == orderDiff || ("2".equals(bean.getOrderTypeFlag()) && ((eTime - sTime - orderDiff % diff) % (L_DAY / 2) == 0 || (eTime - sTime - orderDiff) % (L_DAY / 2) == 0))){
                        ncMap.get(time).remove(key);
                    }*/
                }

                sTime += L_DAY;
            }while(sTime < eTime);

            sTime = bean.getBeginTime().getTime();
            do {//计算月级别的数据

                String time = longToString(sTime, MONTH_TIME_PATTERN);

                if(!ncMonthMap.containsKey(time)){
                    ncMonthMap.put(time, new ArrayList<>());
                }
                if(isAdd){
                    ncMonthMap.get(time).add(key);
                }else{
                    /*HomeCalcOrderInfo serviceBean = serviceBeanMap.get(bean.getRefundServiceId());
                    long s1 = getNowMonthFirstDay(sTime) + offset;
                    long s2 = serviceBean.getBeginTime().getTime();
                    long s = s2 < s1 ? s1 : s2;
                    //退款开始时间 小于 订单开始时间 && 退款结束时间 大于订单结束时间
                    long e1 = getNextMonthFirstDay(sTime) + offset;
                    long e2 = serviceBean.getEndTime().getTime();
                    long e = e1 < e2 ? e1 : e2;

                    if(sTime <= s && bean.getEndTime().getTime() >= e){
                        ncMonthMap.get(time).remove(key);
                    }*/

                    /*HomeCalcOrderInfo serviceBean = serviceBeanMap.get(bean.getRefundServiceId());
                    orderDiff = serviceBean.getEndTime().getTime() - serviceBean.getBeginTime().getTime();

                    long diff = getNowYearLong(sTime);
                    if(eTime - sTime >= diff || eTime - sTime == orderDiff % diff || eTime - sTime == orderDiff || ("2".equals(bean.getOrderTypeFlag()) && ((eTime - sTime - orderDiff % diff) % (L_DAY / 2) == 0 || (eTime - sTime - orderDiff) % (L_DAY / 2) == 0))){
                        ncMonthMap.get(time).remove(key);
                    }*/
                }

                //获取下个月的第一天
                sTime = getNextMonthFirstDay(sTime) + offset;
            }while (sTime < eTime);

            sTime = bean.getBeginTime().getTime();
            do {//计算年级别的数据

                String time = longToString(sTime, YEAR_TIME_PATTERN);

                if(!ncYearMap.containsKey(time)){
                    ncYearMap.put(time, new ArrayList<>());
                }
                if(isAdd){
                    ncYearMap.get(time).add(key);
                }else{
                    /*HomeCalcOrderInfo serviceBean = serviceBeanMap.get(bean.getRefundServiceId());
                    long s1 = getNowYearFirstDay(sTime) + offset;
                    long s2 = serviceBean.getBeginTime().getTime();
                    long s = s2 < s1 ? s1 : s2;
                    //退款开始时间 小于 订单开始时间 && 退款结束时间 大于订单结束时间
                    long e1 = getNextYearFirstDay(sTime) + offset;
                    long e2 = serviceBean.getEndTime().getTime();
                    long e = e1 < e2 ? e1 : e2;

                    if(sTime <= s && bean.getEndTime().getTime() >= e){
                        ncYearMap.get(time).remove(key);
                    }*/

                    /*HomeCalcOrderInfo serviceBean = serviceBeanMap.get(bean.getRefundServiceId());
                    orderDiff = serviceBean.getEndTime().getTime() - serviceBean.getBeginTime().getTime();

                    long diff = getNowYearLong(sTime);
                    if(eTime - sTime >= diff || eTime - sTime == orderDiff % diff || eTime - sTime == orderDiff || ("2".equals(bean.getOrderTypeFlag()) && ((eTime - sTime - orderDiff % diff) % (L_DAY / 2) == 0 || (eTime - sTime - orderDiff) % (L_DAY / 2) == 0))){
                        ncYearMap.get(time).remove(key);
                    }*/
                }

                //获取下一年的第一天
                sTime = getNextYearFirstDay(sTime) + offset;
            }while (sTime < eTime);
        });
    }

    private void calcPatient(List<HomeCalcOrderInfo> list, Map<String, List<String>> pcMap, Map<String, List<String>> pcMonthMap, Map<String, List<String>> pcYearMap) {
        Map<String, Integer> distinct = new HashMap<>();
        Map<String, HomeCalcOrderInfo> serviceBeanMap = new HashMap<>();
        list.forEach(bean -> {
            //去除重复的serviceId
            String serviceId = bean.getServiceId();
            if(distinct.containsKey(serviceId)){
                return ;
            }
            log(bean);

            long orderDiff = bean.getEndTime().getTime() - bean.getBeginTime().getTime();

            distinct.put(serviceId, null);
            serviceBeanMap.put(serviceId, bean);

            //计算是增加还是减少
            boolean isAdd = !"3".equals(bean.getOrderType());

            String key = bean.getPatientName() + bean.getPhone();

            long sTime = bean.getBeginTime().getTime(),
                    eTime = bean.getEndTime().getTime(),
                    offset = getDayOffset(bean.getBeginTime()),
                    prevOffset = 0;

            if(!isAdd){
                prevOffset = getDayOffset(serviceBeanMap.get(bean.getRefundServiceId()).getBeginTime());
            }

            do{//计算天级别的数据
                String time = longToString(sTime);

                if(!pcMap.containsKey(time)){
                    pcMap.put(time, new ArrayList<>());
                }
                if(isAdd){
                    pcMap.get(time).add(key);
                }else{
                    /*long diff = L_DAY;
                    if(eTime - sTime >= diff || eTime - sTime == orderDiff % diff || eTime - sTime == orderDiff || ("2".equals(bean.getOrderTypeFlag()) && ((eTime - sTime - orderDiff % diff) % (L_DAY / 2) == 0 || (eTime - sTime - orderDiff) % (L_DAY / 2) == 0))){
                        pcMap.get(time).remove(key);
                    }*/
                }

                sTime += L_DAY;
            }while(sTime < eTime);

            sTime = bean.getBeginTime().getTime();
            do {//计算月级别的数据

                String time = longToString(sTime, MONTH_TIME_PATTERN);

                if(!pcMonthMap.containsKey(time)){
                    pcMonthMap.put(time, new ArrayList<>());
                }
                if(isAdd){
                    pcMonthMap.get(time).add(key);
                }else{
                    /*HomeCalcOrderInfo serviceBean = serviceBeanMap.get(bean.getRefundServiceId());
                    long s1 = getNowMonthFirstDay(sTime) + offset;
                    long s2 = serviceBean.getBeginTime().getTime();
                    long s = s2 < s1 ? s1 : s2;
                    //退款开始时间 小于 订单开始时间 && 退款结束时间 大于订单结束时间
                    long e1 = getNextMonthFirstDay(sTime) + offset;
                    long e2 = serviceBean.getEndTime().getTime();
                    long e = e1 < e2 ? e1 : e2;

                    if(sTime <= s && bean.getEndTime().getTime() >= e){
                        pcMonthMap.get(time).remove(key);
                    }*/
                    /*HomeCalcOrderInfo serviceBean = serviceBeanMap.get(bean.getRefundServiceId());
                    orderDiff = serviceBean.getEndTime().getTime() - serviceBean.getBeginTime().getTime();

                    long diff = getNowMonthLong(sTime);
                    if(eTime - sTime >= diff || eTime - sTime == orderDiff % diff || eTime - sTime == orderDiff || ("2".equals(bean.getOrderTypeFlag()) && ((eTime - sTime - orderDiff % diff) % (L_DAY / 2) == 0 || (eTime - sTime - orderDiff) % (L_DAY / 2) == 0))){
                        pcMonthMap.get(time).remove(key);
                    }*/

                }

                //获取下个月的第一天
                sTime = getNextMonthFirstDay(sTime) + offset;
            }while (sTime < eTime);

            sTime = bean.getBeginTime().getTime();
            do {//计算年级别的数据

                String time = longToString(sTime, YEAR_TIME_PATTERN);

                if(!pcYearMap.containsKey(time)){
                    pcYearMap.put(time, new ArrayList<>());
                }
                if(isAdd){
                    pcYearMap.get(time).add(key);
                }else{
                    /*HomeCalcOrderInfo serviceBean = serviceBeanMap.get(bean.getRefundServiceId());
                    long s1 = getNowYearFirstDay(sTime) + offset;
                    long s2 = serviceBean.getBeginTime().getTime();
                    long s = s2 < s1 ? s1 : s2;
                    //退款开始时间 小于 订单开始时间 && 退款结束时间 大于订单结束时间
                    long e1 = getNextYearFirstDay(sTime) + offset;
                    long e2 = serviceBean.getEndTime().getTime();
                    long e = e1 < e2 ? e1 : e2;

                    if(sTime <= s && bean.getEndTime().getTime() >= e){
                        pcYearMap.get(time).remove(key);
                    }*/
                   /* HomeCalcOrderInfo serviceBean = serviceBeanMap.get(bean.getRefundServiceId());
                    orderDiff = serviceBean.getEndTime().getTime() - serviceBean.getBeginTime().getTime();

                    long diff = getNowYearLong(sTime);
                    if(eTime - sTime >= diff || eTime - sTime == orderDiff % diff || eTime - sTime == orderDiff || ("2".equals(bean.getOrderTypeFlag()) && ((eTime - sTime - orderDiff % diff) % (L_DAY / 2) == 0 || (eTime - sTime - orderDiff) % (L_DAY / 2) == 0))){
                        pcYearMap.get(time).remove(key);
                    }*/
                }

                //获取下一年的第一天
                sTime = getNextYearFirstDay(sTime) + offset;
            }while (sTime < eTime);
        });

        //患者个数需要去重
        pcMap.forEach((k, v) -> this.distinctList(v));
        pcMonthMap.forEach((k, v) -> this.distinctList(v));
        pcYearMap.forEach((k, v) -> this.distinctList(v));
    }

    //一些固定的变量
    private static final long L_HOUR = 1000 * 60 * 60;
    private static final long L_DAY = L_HOUR * 24;
    private static final String FULL_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    private static final String DAY_TIME_PATTERN = "yyyy-MM-dd";
    private static final String MONTH_TIME_PATTERN = "yyyy-MM";
    private static final String YEAR_TIME_PATTERN = "yyyy";

    //一些辅助方法

    //打印测试
    private SimpleDateFormat sdf = new SimpleDateFormat(FULL_TIME_PATTERN);
    private void log(HomeCalcOrderInfo bean){

        String log = "log: sTime: {1}, eTime: {2}, price: {3}, pay: {4}, name: {5}, status: {6}";
        log = log.replace("{1}", sdf.format(bean.getBeginTime()));
        log = log.replace("{2}", sdf.format(bean.getEndTime()));
        log = log.replace("{3}", bean.getActualTotalPrice()+"");
        log = log.replace("{4}", bean.getTotalPay()+"");
        log = log.replace("{5}", bean.getPatientName());
        log = log.replace("{6}", bean.getOrderType());

        System.out.println(log);
    }

    //list保持引用去重
    private void distinctList(List<?> list){
        List distinct = list.stream().distinct().collect(Collectors.toList());
        list.clear();
        list.addAll(distinct);
    }

    //获取当前的偏移时间
    private long getDayOffset(Date time) {
        long e = time.getTime();

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        calendar.set(Calendar.HOUR, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);

        long s = calendar.getTime().getTime();

        return e - s;
    }

    //获取当天的开始时间
    private Date getNowStartTime() {
        try {
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat();
            sdf.applyPattern(DAY_TIME_PATTERN);

            String nowDay = sdf.format(date) + " 00:00:00";

            sdf.applyPattern(FULL_TIME_PATTERN);

            return sdf.parse(nowDay);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    //把long时间转换成日期
    private String longToString(long time){
        return longToString(time,DAY_TIME_PATTERN);
    }
    //把long时间转换成日期
    private String longToString(long time, String pattern){
        Date date = new Date();
        date.setTime(time);
        return new SimpleDateFormat(pattern).format(date);
    }

    //计算当前日期是否为本月最后一天
    private int calcIsMonthLast(String time){

        try {
            Calendar calendar = Calendar.getInstance();

            SimpleDateFormat sdf = new SimpleDateFormat(DAY_TIME_PATTERN);
            Date date = sdf.parse(time);

            calendar.setTime(date);

            int thisMonth = calendar.get(Calendar.MONTH);
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            int afterMonth = calendar.get(Calendar.MONTH);

            return thisMonth != afterMonth ? 1: 0;
        } catch (ParseException e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取当前月的时间长度
     */
    private long getNowMonthLong(long time) {
        Calendar calendar = Calendar.getInstance();
        Date date = new Date(time);
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);

        long s = calendar.getTime().getTime();
        calendar.add(Calendar.MONTH, 1);
        long e = calendar.getTime().getTime();
        return e - s;
    }

    /**
     * 获取当前年的时间长度
     */
    private long getNowYearLong(long time) {
        Calendar calendar = Calendar.getInstance();
        Date date = new Date(time);
        calendar.setTime(date);
        calendar.set(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);

        long s = calendar.getTime().getTime();
        calendar.add(Calendar.YEAR, 1);
        long e = calendar.getTime().getTime();
        return e - s;
    }

    /**
     * 获取当前月的第一天的long值
     */
    private long getNowMonthFirstDay(long time){
        try {
            Calendar calendar = Calendar.getInstance();

            Date date = new Date(time);

            calendar.setTime(date);
            calendar.set(Calendar.DAY_OF_MONTH, 1);

            return calendar.getTime().getTime();
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取下个月的第一天的long值
     */
    private long getNextMonthFirstDay(long time){
        try {
            Calendar calendar = Calendar.getInstance();

            Date date = new Date(time);

            calendar.setTime(date);
            calendar.add(Calendar.MONTH, 1);
            calendar.set(Calendar.DAY_OF_MONTH, 1);

            return calendar.getTime().getTime();
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取当前年的第一天的long值
     */
    private long getNowYearFirstDay(long time) {
        try {
            Calendar calendar = Calendar.getInstance();

            Date date = new Date(time);

            calendar.setTime(date);
            calendar.set(Calendar.MONTH, 0);
            calendar.set(Calendar.DAY_OF_MONTH, 1);

            return calendar.getTime().getTime();
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取下一年的第一天的long值
     */
    private long getNextYearFirstDay(long time) {
        try {
            Calendar calendar = Calendar.getInstance();

            Date date = new Date(time);

            calendar.setTime(date);
            calendar.add(Calendar.YEAR, 1);
            calendar.set(Calendar.MONTH, 0);
            calendar.set(Calendar.DAY_OF_MONTH, 1);

            return calendar.getTime().getTime();
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    //获取当月有多少天
    private int monthCount(String time){
        try {
            Date date = new SimpleDateFormat(DAY_TIME_PATTERN).parse(time);

            Calendar a = Calendar.getInstance();
            a.setTime(date);

            a.set(Calendar.DATE, 1);            //把日期设置为当月第一天
            a.roll(Calendar.DATE, -1);  //日期回滚一天，也就是最后一天
            return a.get(Calendar.DATE);
        } catch (ParseException e) {
            e.printStackTrace();
            return 30;
        }
    }

    //判断字符串类型的是否为数字
    private boolean isNumber(String str){
        if(str == null || "".equals(str)){
            return false;
        }

        Pattern pattern = Pattern.compile("[0-9]+");
        return pattern.matcher(str).matches();
    }

    public static void main(String[] args) {
        System.out.println("{1}a".replace("{1}", ""));
    }



}
